package cn.bitkit.assist.code;

import cn.bitkit.assist.code.vo.CodeVO;
import cn.bitkit.assist.code.vo.EntityVO;
import cn.bitkit.assist.code.vo.OutputVO;
import cn.bitkit.assist.code.vo.ProjectVO;
import cn.bitkit.base.util.PathUtil;
import cn.bitkit.tools.file.FileUtil;
import cn.bitkit.tools.common.IOUtil;
import cn.bitkit.base.util.StringUtil;
import cn.bitkit.tools.file.TextHelper;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 
 * @author changbo
 *
 */
@Slf4j
@Setter
public abstract class BaseCreator {
    
    protected CodeVO codeVO;
    protected EntityVO entityVO;
    protected OutputVO outputVO;
    protected ProjectVO projectVO;

    public abstract void create();


    protected String getTemplate(String tplFile) {
        InputStream is = this.getClass().getClassLoader().getResourceAsStream("code/"+tplFile);
        return IOUtil.readString(is);
    }

    protected void writeText(String text, String fileName) {
        if(outputVO.getWriteConsole()) {
            System.out.println("===============================");
            System.out.println(text);
        }
        if(outputVO.getWriteFile()) {
            System.out.println(fileName);
            FileUtil.createFile(fileName, text);
        }
    }


    protected String getImportClass(boolean isDTO) {
        List<String> list = entityVO.getFieldList().stream()
            .filter(e -> !e.getFieldClass().getName().startsWith("java.lang"))
            .map(e -> "import "+e.getFieldClass().getName()+";")
            .distinct()
            .collect(Collectors.toList());
        if(isDTO) {
            long dateCount = entityVO.getFieldList().stream()
                    .filter(e -> Date.class == e.getFieldClass() || LocalDateTime.class == e.getFieldClass())
                    .count();
            if(dateCount > 0) {
                list.add("import org.springframework.format.annotation.DateTimeFormat;");
                list.add("import com.fasterxml.jackson.annotation.JsonFormat;");
            }
            if(codeVO.getAddSwagger()){
                list.add("import io.swagger.v3.oas.annotations.media.Schema;");
            }
        }
        return list.stream().sorted().collect(Collectors.joining("\r\n"));
    }

    protected String getFieldList(boolean isDTO) {
        final String template = "    /** ${comment} */\r\n"
                + "${annotation}"
                + "    private ${simpleFieldClass} ${field};";

        final String dateAnnotation = "    @JsonFormat(pattern=\"yyyy-MM-dd HH:mm:ss\", timezone = \"GMT+8\") \n"
                + "    @DateTimeFormat(pattern=\"yyyy-MM-dd HH:mm:ss\")\r\n";
        final String swaggerAnnotation = "    @Schema(title=\"${field}\", description = \"${fieldTitle}\")\n";
        return entityVO.getFieldList().stream().map(e -> {
            String annotation = "";
            if(isDTO) {
                if(Date.class == e.getFieldClass()) {
                    annotation += dateAnnotation;
                }
                if(codeVO.getAddSwagger()){
                    annotation += swaggerAnnotation;
                }
            }
            if(StringUtil.hasValue(annotation)){
                annotation = TextHelper.loadString(annotation)
                        .setValue("field", e.getField())
                        .setValue("fieldTitle", e.getName())
                        .getText();
            }
            TextHelper builder = TextHelper.loadString(template);
            builder.setValue("comment", e.getName());
            builder.setValue("annotation", annotation);
            builder.setValue("simpleFieldClass", e.getFieldClass().getSimpleName());
            builder.setValue("field", e.getField());
            return builder.getText();
        }).collect(Collectors.joining("\r\n"));
    }


    protected String getJavaFile(String type){
        return getJavaFile(type, StringUtil.upperFirst(type));
    }

    protected String getJavaFile(String type, String suffix){
        return getJavaFile(type, "", suffix);
    }

    protected String getJavaFile(String type, String subModule, String suffix){
        String path = PathUtil.asPath(projectVO.getAbsoluteJavaFolder(), type, projectVO.getModuleName(), subModule);
        return path + entityVO.getEntityName() + suffix + ".java";
    }

}
